#version 460
#extension GL_GOOGLE_include_directive : enable
#extension GL_EXT_nonuniform_qualifier : enable
#extension GL_EXT_shader_explicit_arithmetic_types_int64 : require
#extension GL_EXT_shader_explicit_arithmetic_types_int16 : require
#extension GL_EXT_shader_explicit_arithmetic_types_int8 : require


#include "../../../../core/shader_binding_ID.h"
#include "../../../../core/shader_std.h"
#include "../../../../core/shader_built_in_functions.h"

//#include "PBR_MaterialAtt.glsl"


layout(location=0) out vec4 outColor;
//layout(location=1) out vec4 outVert;
//layout(location=2) out vec4 outNormal;

layout(set = 1, binding = DEF_BINDING_WIDGET_Texture) uniform sampler2D texColor[];

layout(set = 2, binding = DEF_BindID_TextureCube) uniform samplerCube texEnv[];
layout(set = 2, binding = DEF_BindID_TextureShadow) uniform sampler2D texShadow[];
layout(set = 2, binding = DEF_BindID_TexCubeShadow) uniform samplerCube texCubeShadow[];
layout(set = 2, binding = DEF_BindID_GBufferImage)  uniform sampler2D GBuffer_Image[];

layout(set = 2, binding = DEF_BindID_CompositingShadow) uniform sampler2D compositing_shadow[];


layout(std140, set = 2, scalar, binding = DEF_BindID_GlobalTextAtt) uniform Buf0 {
	S_GlobalAtt_RasterPostCompositing m_constPush;
};

//每个灯光的阴影图层数量
layout(std430, set = 2, column_major, scalar, binding = DEF_BindID_TexShadow_LightIndex) readonly buffer Buf1 {
	S_LightIndex m_LightIndex[];
};

//光投影矩阵
layout(std430, set = 2, column_major, scalar, binding = DEF_BindID_TexShadow_PVMatrix) readonly buffer Buf3 {
	mat4 m_LightArea_PVMatrix[];
};

//区域光属性
layout(std430, set = 2, column_major, scalar, binding = DEF_BindID_TexShadow_AreaLight) readonly buffer Buf2 {
	S_LightArea m_LightArea[];
};

//材质属性
layout(std430, set = 2, scalar, column_major, binding = DEF_BINDING_TasterBindID_MaterialID) readonly buffer Buf4 {
	S_Material gMaterial[];
};




layout(location = 0) in vec3 inEyeDir;
layout(location = 1) in vec3 inNormal;
layout(location = 2) in vec4 inVert;
layout(location = 3) in flat mat4 inCameraView;
layout(location = 7) in flat uint inMaterialID;
layout(location = 8) in float inElementID;
layout(location = 9) in vec2 inUV;

layout(early_fragment_tests) in;


#include "../光栅渲染/灯光阴影.glsl"
#include "../光栅渲染/纹理模糊计算.glsl"

vec3 f_ComputeUniformHemisphereSample(vec2 uv) {
	// 计算phi（方位角），从0到2π
	float phi = atan(uv.y - 0.5, uv.x - 0.5) + M_PI;
	
	// 使用sin(theta)分布来调整theta采样，实现更均匀的采样
	float theta = acos(sqrt(1.0 - uv.y));

	// 将调整后的phi和theta转换为笛卡尔坐标系下的向量
	float sinTheta = sin(theta);
	float cosTheta = cos(theta);
	float sinPhi = sin(phi);
	float cosPhi = cos(phi);

	// 返回半球面上的点
	return vec3(sinTheta * cosPhi, cosTheta, sinTheta * sinPhi);
	//return vec3(sinTheta * sinPhi, cosTheta, sinTheta * cosPhi);
}

vec3 f_SphereSampling_toWorld3(vec3 ss, vec3 N, vec3 offsetDir) {
    // 初始化一个与N不同的上向量up，避免与N平行
    vec3 up = normalize(vec3(0, 1, 0) + offsetDir + f_random(ss.xz) * 0.00001);

    // 计算右向量right，使用cross函数计算叉乘
    vec3 right = normalize(cross(N, up));

    // 重新计算上向量up，确保它与N和right都垂直
    up = normalize(cross(right, N));

    // 构造局部坐标系的矩阵
    mat3 TBN = mat3(right, up, N);

    // 使用局部坐标系的矩阵将球坐标系下的采样点转换到世界坐标系
    vec3 worldPosition = TBN * vec3(ss.x, ss.z, ss.y);

    return worldPosition;
}

float lerp(float a, float b, float f) {
    return a + f * (b - a);
}



const vec3 w = vec3(0.2125,0.7154,0.0721);

void main(void) {
	float stepSample = max(m_constPush.m_resolutionRatio.x, m_constPush.m_resolutionRatio.y);
	//vec2 sampleOffsetSize = vec2(1.0) / stepSample;
	vec2 invResolution = 1.0 / m_constPush.m_resolutionRatio;

	vec2 screenCoords = vec2(gl_FragCoord.xy) / m_constPush.m_resolutionRatio;
	outColor = vec4(0.2,0.0,0.0,1);
	//return;
	vec3 rv = reflect(normalize(-inEyeDir), inNormal);
	
	S_Material mate = gMaterial[inMaterialID];

	vec3 irradiance = vec3(0);
	vec3 albedo = vec3(0.4,0.2,0.1);
	vec3 metallicRoughness = vec3(0.1);
	vec3 F0 = vec3(0.04);

	//切线法线
	vec3 N = normalize(inNormal);
	vec3 R = reflect(normalize(inEyeDir), N);
	float VD = 1 / length(inEyeDir) * 10;

	//环境纹理
	vec4 env = texture(texEnv[0], N, 0);
	irradiance.rgb = env.rgb;
	
	vec4 env_s = texture(texEnv[1], rv, 0);
	irradiance += vec3(env_s.rgb * env_s.a) * mate.m_reflect;
	irradiance *= m_constPush.m_envIntensity;

	vec3 specular = mate.m_specular * inElementID*inElementID;
	//视线高光
	float vs = max(dot(normalize(-inEyeDir), inNormal), 0);
	vs = pow(vs, 60) * VD;
	specular *= vs;
	


	vec3 lightColor = vec3(0.001);
	float s = 0;
	float a = 0;
	float contactShadow = 0;
	float maxDis = 0;
	
	for(uint i = 0; i < uint(m_constPush.light_Num); ++i){
		S_LightIndex light = m_LightIndex[m_constPush.light_Offset + i];

		switch(uint(light.m_lightType)){
			case DEF_ObType_Ligth_Parallel : {
				break;
			}
			case DEF_ObType_Ligth_Point : {
				break;
			}
			case DEF_ObType_Ligth_Area : {
				S_LightArea area = m_LightArea[light.m_attIndex];
				
				/******************** 灯光计算 ******************/
				
				vec3 L = (area.m_pos - inVert.xyz);
				float ld = max(dot(N, -area.m_dir), 0) * max(dot(normalize(L), -area.m_dir), 0);
				//float ld = max(dot(normalize(L), -area.m_dir), 0);

				vec3 lightIntensity = area.m_color;
				//lightColor += vec3(ld) * area.m_intensity;
				
				
				float LI = 1 - smoothstep(0, 1, clamp(0, area.m_dis, length(L)) / area.m_dis);
				lightIntensity *= vec3(LI) * pow(ld, 3) * area.m_intensity;
				lightIntensity += pow(max(dot(R, normalize(L)), 0) * ld, 10) * (1-mate.m_roughness) * specular;
				
				lightColor += lightIntensity;
				
				break;
			}
			case DEF_ObType_Ligth_Spot : {
				break;
			}
		}
		//outColor.xyz = inVert.xyz;
		s = max(s, a);
	}

	//outColor.xyz = vec3(maxDis);
	//return;

	//return;
	//阴影汇集
	s /= float(m_constPush.light_Num);
	s *= m_constPush.m_shadowIntensity;
	s = 1 - clamp(s, 0, 1);
	s = (s - 0.3) * 1.4 + 0.3;
	
	

	

	
	float sampleDelta = 0.5;
	int nrSamples = 0; 
	

	


	//vec2 sampleOffset = gl_SamplePosition.xy * invResolution * 2;
	//vec4 OriPoint = inCameraView * vec4(inVert.xyz, 0);
	float AO = 0;
	//float AO = f_ssao(inCameraView, invResolution, screenCoords);

	const float desiredFovY = radians(mate.m_roughness * 180);
	//const int ao_X_ItNum = (m_constPush.m_AONum >> 16);
	//const int ao_Y_ItNum = (m_constPush.m_AONum & 0x0000ffff);
	const vec2 spaceSampleOffset = vec2(1.0f/(m_constPush.m_AO_X_Sample>>2), float(1.0 / m_constPush.m_AO_Y_Sample));

	//vec4 coVert = texture(GBuffer_Image[DEF_GBuffer_Vert], gl_FragCoord.xy * invResolution);
	//vec2 currentUV = gl_FragCoord.xy * invResolution;
	float courrentPointZ = (inCameraView * vec4(inVert.xyz, 0)).z;
	//float zInv = 1 / m_constPush.m_radiusAO;
	float ao_tInv = 1 / m_constPush.m_thicknessAO;
	float w = gl_FragCoord.z * gl_FragCoord.w * 2 + 1;

	

	//s = 1 - clamp(s, 0, 1);
	//s = min(s, AO);
	float c = s * AO;
	//AO *= s;
	
	//irradiance *= s;
	//float d1 = dot(w, irradiance);
	//float d2 = dot(w, lightColor);
	//irradiance = vec3(0.3);
	//c += 0.1;
	
	outColor.xyz = (mate.m_color * (1 - mate.m_reflect) * mate.m_roughness);
	outColor.xyz *= (4 / (inElementID + 1)) * 0.25;
	outColor.xyz = (irradiance + outColor.xyz + lightColor) * s;
	////outColor.xyz = irradiance * s + lightColor;
	outColor.xyz += specular;
	return;
}


